#include "temprature.h"

typedef struct temprature_point
{
	float res_value;
	float temprature;
} temprature_point_t;

static temprature_point_t ntc_table[] = {
	{531, 125},
	{596, 120},
	{672, 115},
	{758, 110},
	{858, 105},
	{974, 100},
	{1110, 95},
	{1268, 90},
	{1452, 85},
	{1669, 80},
	{1925, 75},
	{2228, 70},
	{2586, 65},
	{3014, 60},
	{3535, 55},
	{4161, 50},
	{4917, 45},
	{5834, 40},
	{6948, 35},
	{8315, 30},
	{10000, 25},
	{12081, 20},
	{14674, 15},
	{17926, 10},
	{22021, 5},
	{27219, 0},
	{33892, -5},
	{42506, -10},
	{53650, -15},
	{68237, -20},
	{87559, -25},
	{113347, -30},
	{148174, -35},
	{195652, -40},
};

/*
 * 线性插值函数，根据两个温度点之间的坐标，求出两点之间的线性关系，并将真实值带
 * 入其中，求解出真实阻值对应的真实温度。
 */
static float line_value(int big_res_value, int low_temp,
						int small_res_value, int high_temp,
						float real_res_value)
{
	float k = ((low_temp - high_temp) / (big_res_value - small_res_value));
	float b = low_temp / (-1 * k * big_res_value);
    
	return (k * real_res_value + b);
}

/*
 * 根据采集到的真实阻值求解对应的温度
 */
static float calculate(float value)
{
	for (int i = 0; i < 34; i++)
	{
		// 找出真实阻值所处的位置
		if (value >= ntc_table[i].res_value)
		{
			float real_temp = 0.0f;
			real_temp = line_value(ntc_table[i + 1].res_value, ntc_table[i + 1].temprature,
								   ntc_table[i].res_value, ntc_table[i].temprature, value);
			return real_temp;
		}
	}
	return -50.0f; // 返回超出传感器量程，错误
}

#define VREF (5.0f) // ADC 参考电压 V
#define RF (10000)	// 分压电压参考电阻 ohm

/**
 * @brief	获取 NTC 的温度值
 * @param	data - 从 ADC 中获取的 12bits 采样值
 */
void get_temprature(temp_sensor_t *sensor, unsigned short data)
{
	/* 根据 ADC 求出阻值 */
	float voltage = ((float)data / 4095) * 5;
	float rx = (voltage * RF) / (VREF - voltage);
	*sensor = calculate(rx);
}
